package com.biubiushop.Socket.NIOChatRoom;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Set;

/**
 * @author chenjia
 * @date 2019/7/19
 * 利用多线程实现接收消息
 **/
public class NioClientHandler implements Runnable {

    private Selector selector;

    public NioClientHandler(Selector selector) {
        this.selector = selector;
    }

    @Override
    public void run() {
        while (true) {
            //获取channel数量
            try {
                int readyChannels = 0;
                readyChannels = selector.select();
                if (readyChannels == 0)
                    continue;
                //获取可用channel集合
                Set<SelectionKey> selectionKeys = selector.selectedKeys();

                Iterator<SelectionKey> iterator = selectionKeys.iterator();

                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    iterator.remove();

                    //根据就绪状态,调用对应方法处理业务逻辑
                    //可读事件
                    if (selectionKey.isReadable()) {
                        readHandler(selectionKey);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    private void readHandler(SelectionKey selectionKey) throws IOException {
        //从selectionKey中获取已就绪的channel
        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();

        //创建buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

        //循环读取服务端响应信息
        String response = "";
        while (socketChannel.read(byteBuffer) > 0) {
            //切换buffer为读模式
            byteBuffer.flip();

            response += Charset.forName("UTF-8").decode(byteBuffer);

        }

        //将channel再次注册到seletor上,监听可读事件
        socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ);

        //将服务端响应信息打印到本地
        if (response.trim().length() > 0) {
            System.out.println("服务端发送过来的消息为:" + response);
        }
    }
}
